﻿using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Accord.Imaging.Filters;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.Util;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using MathNet.Numerics.LinearAlgebra;

namespace MyWatermark
{


    //// 参数配置类
    //public class WatermarkSettings
    //{
    //    public float Alpha { get; set; } = 0.05f;  // 水印嵌入强度
    //    public int BlockSize { get; set; } = 8;    // 分块尺寸
    //    public double Threshold { get; set; } = 0.5; // 提取阈值
    //    public WaveletTransformer.WaveletType Wavelet { get; set; } = WaveletTransformer.WaveletType.Haar;
    //}

    //// 主处理类
    //public static class DwtWatermarkProcessor
    //{
    //    // 水印嵌入入口
    //    public static void Embed(Image<Rgb24> hostImage,
    //                           string watermarkText,
    //                           string outputPath,
    //                           WatermarkSettings settings)
    //    {
    //        // 1. 图像预处理
    //        var (yChannel, uvChannels) = ImagePreprocessor.ConvertToYuvAndPad(hostImage);

    //        // 2. DWT分解
    //        var dwtResult = WaveletTransformer.DWT2D(yChannel, settings.Wavelet);

    //        // 3. 分块处理LL频带
    //        var blocks = BlockProcessor.PartitionLL(dwtResult.LL, settings.BlockSize);

    //        // 4. 水印编码
    //        var watermarkBits = WatermarkEncoder.ConvertToBits(watermarkText);

    //        // 5. 嵌入核心算法
    //        var modifiedLL = EmbedCore(blocks, watermarkBits, settings);

    //        // 6. 逆DWT重构
    //        var newYChannel = WaveletTransformer.IDWT2D(modifiedLL, dwtResult.HL, dwtResult.LH, dwtResult.HH);

    //        // 7. 合并通道保存
    //        ImageReconstructor.ReconstructAndSave(newYChannel, uvChannels, outputPath);
    //    }

    //    // 水印提取入口
    //    public static string Extract(Image<Rgb24> watermarkedImage,
    //                               int expectedLength,
    //                               WatermarkSettings settings)
    //    {
    //        // 1. 预处理（同嵌入流程）
    //        var (yChannel, _) = ImagePreprocessor.ConvertToYuvAndPad(watermarkedImage);

    //        // 2. DWT分解
    //        var dwtResult = WaveletTransformer.DWT2D(yChannel, settings.Wavelet);

    //        // 3. 分块LL频带
    //        var blocks = BlockProcessor.PartitionLL(dwtResult.LL, settings.BlockSize);

    //        // 4. 提取水印比特
    //        var extractedBits = ExtractCore(blocks, settings);

    //        // 5. 二值化处理
    //        var binaryBits = BitProcessor.KMeansBinarize(extractedBits, expectedLength);

    //        // 6. 解码文本
    //        return WatermarkEncoder.ConvertToString(binaryBits);
    //    }

    //    // 以下是内部核心方法（示意）
    //    private static float[,] EmbedCore(IEnumerable<float[,]> blocks,
    //                                    bool[] watermarkBits,
    //                                    WatermarkSettings settings)
    //    {
    //        // 具体嵌入逻辑...
    //    }

    //    private static List<double> ExtractCore(IEnumerable<float[,]> blocks,
    //                                          WatermarkSettings settings)
    //    {
    //        // 具体提取逻辑...
    //    }
    //}


    ///// <summary>
    ///// 预处理方法
    ///// </summary>
    //public static class ImagePreprocessor
    //{
    //    public static (float[,] Y, float[,] U, float[,] V) ConvertToYuvAndPad(Image<Rgb24> image)
    //    {
    //        // 补白边至偶数尺寸，补白颜色为白色
    //        var paddedImage = PadToEvenDimensions(image);

    //        // 转换为YUV颜色空间，并分离通道
    //        var yuvChannels = ConvertRgbToYuv(paddedImage);
    //        return yuvChannels;
    //    }
    //    private static Image<Rgb24> PadToEvenDimensions(Image<Rgb24> image)
    //    {
    //        int newWidth = image.Width + (image.Width % 2);
    //        int newHeight = image.Height + (image.Height % 2);

    //        // 当不需要填充时直接返回克隆
    //        if (newWidth == image.Width && newHeight == image.Height)
    //            return image.Clone();

    //        // 创建新画布进行绘制
    //        var paddedImage = new Image<Rgb24>(newWidth, newHeight);
    //        paddedImage.Mutate(ctx =>
    //        {
    //            ctx.DrawImage(image, new Point(0, 0), 1f); // 原始内容绘制到左上角
    //            ctx.BackgroundColor(Color.White);          // 设置填充区域颜色
    //        });

    //        return paddedImage;
    //    }
    //    private static (float[,] Y, float[,] U, float[,] V) ConvertRgbToYuv(Image<Rgb24> image)
    //    {
    //        int width = image.Width;
    //        int height = image.Height;
    //        float[,] y = new float[height, width];
    //        float[,] u = new float[height, width];
    //        float[,] v = new float[height, width];
    //        image.ProcessPixelRows(accessor =>
    //        {
    //            for (int yRow = 0; yRow < accessor.Height; yRow++)
    //            {
    //                Span<Rgb24> pixelRow = accessor.GetRowSpan(yRow);
    //                for (int x = 0; x < pixelRow.Length; x++)
    //                {
    //                    Rgb24 rgb = pixelRow[x];
    //                    // 转换公式
    //                    float yVal = 0.299f * rgb.R + 0.587f * rgb.G + 0.114f * rgb.B;
    //                    float uVal = -0.14713f * rgb.R - 0.28886f * rgb.G + 0.436f * rgb.B + 128;
    //                    float vVal = 0.615f * rgb.R - 0.51499f * rgb.G - 0.10001f * rgb.B + 128;
    //                    y[yRow, x] = yVal;
    //                    u[yRow, x] = uVal; v[yRow, x] = vVal;
    //                }
    //            }
    //        });
    //        return (y, u, v);
    //    }
    //}
    //public class WaveletTransformer
    //{
    //    public enum WaveletType { Haar, Daubechies4 }

    //    public float[,] ForwardTransform(float[,] data, int levels = 3)
    //    {
    //        var temp = (float[,])data.Clone();
    //        int size = data.GetLength(0);

    //        for (int level = 0; level < levels; level++)
    //        {
    //            int currentSize = size >> level;
    //            temp = DecomposeLevel(temp, currentSize);
    //        }
    //        return temp;
    //    }

    //    public float[,] InverseTransform(float[,] coeffs, int levels = 3)
    //    {
    //        var temp = (float[,])coeffs.Clone();
    //        int size = coeffs.GetLength(0);

    //        for (int level = levels - 1; level >= 0; level--)
    //        {
    //            int currentSize = size >> level;
    //            temp = ReconstructLevel(temp, currentSize);
    //        }
    //        return temp;
    //    }

    //    #region 核心算法
    //    private float[,] DecomposeLevel(float[,] data, int size)
    //    {
    //        // 水平方向处理
    //        var rowProcessed = new float[size, size];
    //        for (int i = 0; i < size; i++)
    //        {
    //            for (int j = 0; j < size / 2; j++)
    //            {
    //                float avg = (data[i, 2 * j] + data[i, 2 * j + 1]) / 2;
    //                float diff = (data[i, 2 * j] - data[i, 2 * j + 1]) / 2;
    //                rowProcessed[i, j] = avg;
    //                rowProcessed[i, j + size / 2] = diff;
    //            }
    //        }

    //        // 垂直方向处理
    //        var final = new float[size, size];
    //        for (int j = 0; j < size; j++)
    //        {
    //            for (int i = 0; i < size / 2; i++)
    //            {
    //                float avg = (rowProcessed[2 * i, j] + rowProcessed[2 * i + 1, j]) / 2;
    //                float diff = (rowProcessed[2 * i, j] - rowProcessed[2 * i + 1, j]) / 2;
    //                final[i, j] = avg;
    //                final[i + size / 2, j] = diff;
    //            }
    //        }

    //        return final;
    //    }

    //    private float[,] ReconstructLevel(float[,] coeffs, int size)
    //    {
    //        // 垂直方向重构
    //        var colProcessed = new float[size, size];
    //        for (int j = 0; j < size; j++)
    //        {
    //            for (int i = 0; i < size / 2; i++)
    //            {
    //                float a = coeffs[i, j];
    //                float d = coeffs[i + size / 2, j];
    //                colProcessed[2 * i, j] = a + d;
    //                colProcessed[2 * i + 1, j] = a - d;
    //            }
    //        }

    //        // 水平方向重构
    //        var final = new float[size, size];
    //        for (int i = 0; i < size; i++)
    //        {
    //            for (int j = 0; j < size / 2; j++)
    //            {
    //                float a = colProcessed[i, j];
    //                float d = colProcessed[i, j + size / 2];
    //                final[i, 2 * j] = a + d;
    //                final[i, 2 * j + 1] = a - d;
    //            }
    //        }

    //        return final;
    //    }
    //    #endregion

    //    #region 辅助方法
    //    public static void PrintMatrix(float[,] matrix)
    //    {
    //        int size = matrix.GetLength(0);
    //        for (int i = 0; i < size; i++)
    //        {
    //            for (int j = 0; j < size; j++)
    //            {
    //                Console.Write($"{matrix[i, j],7:F2} ");
    //            }
    //            Console.WriteLine();
    //        }
    //    }
    //    #endregion
    //}
    //public class BlockProcessor
    //{
    //    /// <summary>
    //    /// 分块处理策略接口
    //    /// </summary>
    //    public interface IBlockProcessingStrategy
    //    {
    //        float[,] ProcessBlock(float[,] block);
    //    }

    //    /// <summary>
    //    /// 分块参数配置
    //    /// </summary>
    //    public class BlockConfig
    //    {
    //        public int BlockSize { get; set; } = 64;
    //        public int Stride { get; set; } = 32;
    //        public PaddingMode Padding { get; set; } = PaddingMode.Reflect;
    //        public int PaddingSize => BlockSize - Stride;
    //    }

    //    /// <summary>
    //    /// 边界填充模式
    //    /// </summary>
    //    public enum PaddingMode
    //    {
    //        Zero,       // 零填充
    //        Replicate,  // 边缘复制
    //        Reflect     // 镜像反射
    //    }

    //    private readonly BlockConfig _config;

    //    public BlockProcessor(BlockConfig config = null)
    //    {
    //        _config = config ?? new BlockConfig();
    //        ValidateConfig();
    //    }

    //    /// <summary>
    //    /// 执行分块处理
    //    /// </summary>
    //    public float[,] Process(float[,] data, IBlockProcessingStrategy strategy)
    //    {
    //        var padded = ApplyPadding(data);
    //        var blocks = SplitIntoBlocks(padded);

    //        // 并行处理块
    //        var processedBlocks = blocks.AsParallel()
    //            .AsOrdered()
    //            .Select(block => strategy.ProcessBlock(block))
    //            .ToArray();

    //        return MergeBlocks(processedBlocks, padded.GetLength(0));
    //    }

    //    #region 核心算法实现

    //    /// <summary>
    //    /// 带填充的图像预处理
    //    /// </summary>
    //    private float[,] ApplyPadding(float[,] data)
    //    {
    //        int width = data.GetLength(0);
    //        int height = data.GetLength(1);
    //        int pad = _config.PaddingSize;

    //        var padded = new float[width + pad * 2, height + pad * 2];

    //        // 中心区域填充原始数据
    //        CopySubMatrix(data, padded, pad, pad, width, height);

    //        // 各边界填充
    //        PadEdges(padded, width, height, pad);
    //        return padded;
    //    }

    //    /// <summary>
    //    /// 图像分块切割
    //    /// </summary>
    //    private IEnumerable<float[,]> SplitIntoBlocks(float[,] data)
    //    {
    //        int size = _config.BlockSize;
    //        int stride = _config.Stride;
    //        int width = data.GetLength(0);
    //        int height = data.GetLength(1);

    //        for (int y = 0; y <= height - size; y += stride)
    //        {
    //            for (int x = 0; x <= width - size; x += stride)
    //            {
    //                yield return ExtractBlock(data, x, y, size);
    //            }
    //        }
    //    }

    //    /// <summary>
    //    /// 合并处理后的块
    //    /// </summary>
    //    private float[,] MergeBlocks(IEnumerable<float[,]> blocks, int paddedSize)
    //    {
    //        int blockSize = _config.BlockSize;
    //        int stride = _config.Stride;
    //        int width = paddedSize;
    //        int height = paddedSize;

    //        var accumulator = new float[width, height];
    //        var counter = new int[width, height];

    //        int index = 0;
    //        foreach (var block in blocks)
    //        {
    //            int x = (index % ((width - blockSize) / stride + 1)) * stride;
    //            int y = (index / ((width - blockSize) / stride + 1)) * stride;

    //            AccumulateBlock(block, accumulator, counter, x, y);
    //            index++;
    //        }

    //        NormalizeAccumulation(accumulator, counter);
    //        return RemovePadding(accumulator);
    //    }

    //    #endregion

    //    #region 私有辅助方法

    //    private void ValidateConfig()
    //    {
    //        if (_config.BlockSize <= 0)
    //            throw new ArgumentException("Block size must be positive");
    //        if (_config.Stride <= 0 || _config.Stride > _config.BlockSize)
    //            throw new ArgumentException("Invalid stride value");
    //    }

    //    private static float[,] ExtractBlock(float[,] source, int x, int y, int size)
    //    {
    //        var block = new float[size, size];
    //        for (int i = 0; i < size; i++)
    //        {
    //            for (int j = 0; j < size; j++)
    //            {
    //                block[i, j] = source[x + i, y + j];
    //            }
    //        }
    //        return block;
    //    }

    //    private void PadEdges(float[,] padded, int origWidth, int origHeight, int pad)
    //    {
    //        // 左侧填充
    //        PadRegion(padded, 0, pad, pad, origHeight, isVertical: false);
    //        // 右侧填充
    //        PadRegion(padded, origWidth + pad, pad, pad, origHeight, isVertical: false);
    //        // 顶部填充
    //        PadRegion(padded, pad, 0, origWidth, pad, isVertical: true);
    //        // 底部填充
    //        PadRegion(padded, pad, origHeight + pad, origWidth, pad, isVertical: true);
    //        // 四角填充
    //        PadCorners(padded, origWidth, origHeight, pad);
    //    }

    //    private void PadRegion(float[,] data, int startX, int startY, int width, int height, bool isVertical)
    //    {
    //        for (int i = 0; i < width; i++)
    //        {
    //            for (int j = 0; j < height; j++)
    //            {
    //                int srcX = isVertical ? startX + i : startX - j - 1;
    //                int srcY = isVertical ? startY - j - 1 : startY + j;

    //                switch (_config.Padding)
    //                {
    //                    case PaddingMode.Zero:
    //                        data[startX + i, startY + j] = 0;
    //                        break;
    //                    case PaddingMode.Replicate:
    //                        data[startX + i, startY + j] = data[startX, startY];
    //                        break;
    //                    case PaddingMode.Reflect:
    //                        srcX = Math.Clamp(srcX, 0, data.GetLength(0) - 1);
    //                        srcY = Math.Clamp(srcY, 0, data.GetLength(1) - 1);
    //                        data[startX + i, startY + j] = data[srcX, srcY];
    //                        break;
    //                }
    //            }
    //        }
    //    }

    //    private static void AccumulateBlock(float[,] block, float[,] acc, int[,] cnt, int x, int y)
    //    {
    //        for (int i = 0; i < block.GetLength(0); i++)
    //        {
    //            for (int j = 0; j < block.GetLength(1); j++)
    //            {
    //                acc[x + i, y + j] += block[i, j];
    //                cnt[x + i, y + j]++;
    //            }
    //        }
    //    }

    //    private static void NormalizeAccumulation(float[,] acc, int[,] cnt)
    //    {
    //        for (int i = 0; i < acc.GetLength(0); i++)
    //        {
    //            for (int j = 0; j < acc.GetLength(1); j++)
    //            {
    //                if (cnt[i, j] > 0)
    //                    acc[i, j] /= cnt[i, j];
    //            }
    //        }
    //    }

    //    private float[,] RemovePadding(float[,] data)
    //    {
    //        int pad = _config.PaddingSize;
    //        int w = data.GetLength(0) - pad * 2;
    //        int h = data.GetLength(1) - pad * 2;
    //        return ExtractBlock(data, w, h, pad);
    //    }

    //    private static void CopySubMatrix(float[,] src, float[,] dst,
    //        int dstX, int dstY, int width, int height)
    //    {
    //        for (int i = 0; i < width; i++)
    //        {
    //            for (int j = 0; j < height; j++)
    //            {
    //                dst[dstX + i, dstY + j] = src[i, j];
    //            }
    //        }
    //    }

    //    #endregion


    //    // 添加LL子带分块专用配置
    //    public class LLPartitionConfig
    //    {
    //        public int BlockSize { get; set; } = 32;
    //        public bool AllowOverlap { get; set; } = false;
    //        public PaddingMode Padding { get; set; } = PaddingMode.Replicate;
    //    }

    //    /// <summary>
    //    /// 专用于LL子带的分块方法
    //    /// </summary>
    //    public List<float[,]> PartitionLL(float[,] llBand, LLPartitionConfig config = null)
    //    {
    //        var cfg = config ?? new LLPartitionConfig();
    //        ValidateLLConfig(cfg, llBand);

    //        var padded = PrepareLLPadding(llBand, cfg);
    //        return SplitLLBlocks(padded, cfg).ToList();
    //    }

    //    #region LL子带处理私有方法
    //    private void ValidateLLConfig(LLPartitionConfig cfg, float[,] llBand)
    //    {
    //        if (cfg.BlockSize <= 4)
    //            throw new ArgumentException("LL block size too small");

    //        if (llBand.GetLength(0) != llBand.GetLength(1))
    //            throw new ArgumentException("LL band must be square matrix");
    //    }

    //    private float[,] PrepareLLPadding(float[,] llBand, LLPartitionConfig cfg)
    //    {
    //        int size = llBand.GetLength(0);
    //        int targetSize = (int)Math.Ceiling(size / (double)cfg.BlockSize) * cfg.BlockSize;

    //        if (size == targetSize)
    //            return llBand.Clone() as float[,];

    //        var padded = new float[targetSize, targetSize];
    //        CopySubMatrix(llBand, padded, 0, 0);
    //        PadLLEdges(padded, llBand, cfg);
    //        return padded;
    //    }

    //    private void PadLLEdges(float[,] padded, float[,] original, LLPartitionConfig cfg)
    //    {
    //        int origSize = original.GetLength(0);
    //        int pad = padded.GetLength(0) - origSize;

    //        // 右侧填充
    //        for (int i = 0; i < origSize; i++)
    //        {
    //            for (int j = origSize; j < padded.GetLength(1); j++)
    //            {
    //                padded[i, j] = GetPadValue(original, i, origSize - 1, cfg.Padding);
    //            }
    //        }

    //        // 底部填充
    //        for (int i = origSize; i < padded.GetLength(0); i++)
    //        {
    //            for (int j = 0; j < padded.GetLength(1); j++)
    //            {
    //                padded[i, j] = GetPadValue(original, origSize - 1, j, cfg.Padding);
    //            }
    //        }
    //    }

    //    private IEnumerable<float[,]> SplitLLBlocks(float[,] data, LLPartitionConfig cfg)
    //    {
    //        int blockSize = cfg.BlockSize;
    //        int step = cfg.AllowOverlap ? blockSize / 2 : blockSize;

    //        for (int y = 0; y <= data.GetLength(0) - blockSize; y += step)
    //        {
    //            for (int x = 0; x <= data.GetLength(1) - blockSize; x += step)
    //            {
    //                yield return ExtractBlock(data, x, y, blockSize);
    //            }
    //        }
    //    }

    //    private float GetPadValue(float[,] data, int x, int y, PaddingMode mode)
    //    {
    //        return mode switch
    //        {
    //            PaddingMode.Zero => 0,
    //            PaddingMode.Replicate => data[Math.Clamp(x, 0, data.GetLength(0) - 1),
    //                                       Math.Clamp(y, 0, data.GetLength(1) - 1)],
    //            PaddingMode.Reflect => data[data.GetLength(0) - 1 - x,
    //                                      data.GetLength(1) - 1 - y],
    //            _ => 0
    //        };
    //    }
    //    #endregion
    //}
    //public static class DctOperator { /* DCT变换方法 */ }
    //public static class ImageReconstructor { /* 图像重建方法 */ }
    //public static class WatermarkEncoder { /* 编解码方法 */ }
    //public static class BitProcessor { /* 比特处理/聚类方法 */ }
}


